package photo

import (
	"context"
	"fmt"
	"strconv"
	"strings"

	"mall/common/utils/pointy"
	"mall/common/ctxdatax"
	"mall/common/globalkey"
	"mall/common/mqueuex"
	"mall/common/resultx"
	"mall/service/attachment/rpc/attachmentclient"
	"mall/service/forum/api/internal/svc"
	"mall/service/forum/api/internal/types"
	"mall/service/forum/rpc/forumclient"
	"mall/service/user/rpc/userclient"

	"github.com/zeromicro/go-zero/core/logx"
)

type CreatePhotoLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewCreatePhotoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreatePhotoLogic {
	return &CreatePhotoLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *CreatePhotoLogic) CreatePhoto(req *types.CreatePhotoReq, ip string) (resp *types.BaseDataInfo, err error) {
	userId := ctxdatax.GetUserId(l.ctx)
	if userId == 0 {
		return nil, resultx.NewErrCode(resultx.TOKEN_EXPIRE_ERROR)
	}

	if req.ParentId == nil || *req.ParentId == 0 {
		return nil, resultx.NewErrCode(resultx.FORUM_POST_PARENT_ID_REQUIRED)
	}

	if len(req.Photos) == 0 {
		return nil, resultx.NewErrCode(resultx.FORUM_POST_PHOTO_REQUIRED)
	}

	userInfo, err := l.svcCtx.UserRpc.GetUserAuthByUserId(l.ctx, &userclient.GetUserAuthByUserIdReq{
		PlatformId: pointy.GetPointer(globalkey.ThirdPartyPlatformWechatMini),
		UserId:     pointy.GetPointer(userId),
		WithRank:   pointy.GetPointer(uint32(1)),
	})
	if err != nil {
		logx.Infow("CreatePhoto UserRpc.GetUserAuthByUserId err", logx.Field("detail", err.Error()))
		return nil, resultx.NewErrCode(resultx.USER_GET_INFO_FAILED)
	}

	if userInfo.Openid == nil {
		return nil, resultx.NewErrCode(resultx.USER_GET_INFO_FAILED)
	}

	author := &forumclient.ForumAuthorInfo{
		Id:     userInfo.UserId,
		Name:   userInfo.Nickname,
		Avatar: userInfo.Avatar,
		Ip:     pointy.GetPointer(ip),
		Level:  userInfo.RankId,
	}

	newThumbMap := make(map[string]*types.MediaInfo)
	var newMedia []*forumclient.ForumMediaInfo
	var newMediaIds []string
	var newAttachmentIds []string
	for idx, v := range req.Photos {
		if v.Order == nil {
			v.Order = pointy.GetPointer(uint32(idx))
		}
		if v.Id != nil && len(*v.Id) > 0 {
			if _, ok := newThumbMap[*v.Id]; !ok { // 忽略重复id
				newThumbMap[*v.Id] = v
				newMediaIds = append(newMediaIds, *v.Id)
			}
		} else {
			var thumbnail *uint32
			if v.Thumbnail != nil && *v.Thumbnail {
				thumbnail = pointy.GetPointer(uint32(1))
			}
			newMedia = append(newMedia, &forumclient.ForumMediaInfo{ // 第三方图片
				Uid:       v.Uid,
				Url:       v.Url,
				Thumbnail: thumbnail,
				AltText:   v.AltText,
				Meta:      v.Details,
				Order:     v.Order,
			})
		}
	}
	// 根据 newMediaIds 查询 attachments 记录到 forum_attachment_relationships
	if len(newMediaIds) > 0 {
		res, err := l.svcCtx.AttachmentRpc.BackendGetFileList(l.ctx, &attachmentclient.FileListReq{
			Ids: pointy.GetPointer(strings.Join(newMediaIds, ",")),
		})
		if err != nil {
			return nil, err
		}

		if len(res.List) > 0 {
			for _, v := range res.List {
				var url *string
				if v.Url != nil && len(*v.Url) > 0 {
					url = pointy.GetPointer(fmt.Sprintf("%s%s", l.svcCtx.Config.NfsConf.StaticUrl, *v.Url))
				}
				if url == nil && v.Path != nil && len(*v.Path) > 0 {
					url = pointy.GetPointer(fmt.Sprintf("%s%s", l.svcCtx.Config.NfsConf.ProxyUrl, *v.Path))
				}
				if media, ok := newThumbMap[*v.Id]; ok {
					var thumbnail *uint32
					if media.Thumbnail != nil && *media.Thumbnail {
						thumbnail = pointy.GetPointer(uint32(1))
					}
					newMedia = append(newMedia, &forumclient.ForumMediaInfo{
						Uid:       media.Uid,
						Id:        v.Id,
						Uri:       media.Url,
						Url:       url,
						Thumbnail: thumbnail,
						AltText:   media.AltText,
						Meta:      media.Details,
						Order:     media.Order,
					})
					newAttachmentIds = append(newAttachmentIds, *v.Id)
				}
			}
		}
	}

	if len(newMedia) == 0 {
		return nil, resultx.NewErrCode(resultx.FORUM_POST_PHOTO_REQUIRED)
	}

	var forumId uint64
	if req.ForumId != nil && *req.ForumId > 0 {
		forumId = *req.ForumId
	} else {
		forumId = uint64(l.svcCtx.Config.Query.PhotoForumId)
	}
	var commentStatus *uint32
	if req.CommentStatus != nil && *req.CommentStatus {
		commentStatus = pointy.GetPointer(uint32(1))
	}

	var meta []*forumclient.ForumMetaInfo
	if len(req.Meta) > 0 {
		for _, v := range req.Meta {
			if v.Key == nil || v.Value == nil {
				continue
			}

			if len(strings.TrimSpace(*v.Key)) == 0 || len(strings.TrimSpace(*v.Value)) == 0 {
				continue
			}

			meta = append(meta, &forumclient.ForumMetaInfo{
				Id:    v.Id,
				Key:   v.Key,
				Value: v.Value,
			})
		}
	}

	res, err := l.svcCtx.ForumRpc.CreatePhoto(l.ctx, &forumclient.PostInfo{
		ForumId:       pointy.GetPointer(forumId),
		ParentId:      req.ParentId,
		CommentStatus: commentStatus,
		Author:        author,
		NewMedia:      newMedia,
		Meta:          meta,
	})
	if err != nil {
		return nil, err
	}

	if len(newAttachmentIds) > 0 {
		_, err = l.svcCtx.AttachmentRpc.BackendCreateLog(l.ctx, &attachmentclient.CreateLogReq{
			FileIds:    newAttachmentIds,
			UserId:     pointy.GetPointer(strconv.FormatInt(int64(userId), 10)),
			Put:        pointy.GetPointer(uint32(1)),
			Thumbnail:  pointy.GetPointer(uint32(1)),
			Watermark:  pointy.GetPointer(uint32(1)),
			TermId:     pointy.GetPointer(forumId),
			ObjectId:   pointy.GetPointer(res.Id),
			ObjectType: pointy.GetPointer(uint32(globalkey.AttachmentLogTypeForumPost)),
			Title:      pointy.GetPointer("photo"),
			Slug:       pointy.GetPointer(strconv.FormatInt(int64(*req.ParentId), 10)),
		})
		if err != nil {
			logx.Errorw("CreatePhoto AttachmentRpc BackendCreateLog err", logx.Field("detail", err.Error()))
		}
	}

	var userMeta []*userclient.UserMetaInfo
	userMeta = append(userMeta, &userclient.UserMetaInfo{
		Key:   pointy.GetPointer(mqueuex.UserStatisticForumPhotoNew), // "_photo_new_status"
		Value: pointy.GetPointer("-1"),
	})
	l.svcCtx.UserRpc.SetUserMeta(l.ctx, &userclient.SetUserMetaReq{
		UserId:   pointy.GetPointer(userId),
		MetaKey:  pointy.GetPointer(mqueuex.UserCacheForumPhotoCount), // "_photo_post_count"
		Incr:     pointy.GetPointer(int32(1)),
		UserMeta: userMeta,
	})

	return &types.BaseDataInfo{
		Status:  "ok",
		Message: "发布成功",
	}, nil
}
